/**
* The LightClient Class manages conection to the server and read input and sends output to the server.
* Group: Y1
* @author Mason Kwiat
*/


//package network;
package lightspeed.Network;
import java.io.*;
import java.net.*;

import lightspeed.Backend.GameManager;

public class LightClient
{
	/**
		The socket on which the data channel gets send back and forth from the client to the server.
	*/
	public static Socket socket;
	/**
	* String which will hold the name of the client
	*/
	public String clientName;
	/**
	* String which will hold the name of the address of the server
	*/
	public String serverAddress;

	public static int clientNumber;
	/**
	* ClientPacket object stores the most updated information from the client that is bound to be send to the server.
	*/
	public ClientPacket cpacket;
	/**
	* ServerPacket object stores the most recently recieved information packet form the server
	*/
	public static ServerPacket spacket;

	private boolean connected;
	
	private String[] oldMessages;
	
	
	//testing only
	public static void main(String[] args)
	{
//		LightClient lc = new LightClient("127.0.0.1", "frodo");
	}
	//
	/**
	*	Constructor: creates an instance of the lightclient.
	*	Sets the socket and the serpacket to null
	*	Sets the "name" string arguement to the clientName String variable.
	*	Sets the "ip" strign arguement to the serverAddress string variable.
	*	Opens up communication betwee the client and server on the specified IP addresss.
	*	@param name The name of the client.
	*	@param ip The address of Client's server
	* 	@exception throws an input/output exception if there is some problem in client's input.
	*/
	
	public LightClient(String ip, String name) throws IOException
	{
		socket = null;
		spacket = null;
		
		connected = false;
		
		clientName = name;
		serverAddress = ip;
		
		cpacket = new ClientPacket(clientName);
		
//		try
//		{
			System.out.println("attempting connection...");
            socket = new Socket(serverAddress, 5195);
            
            connected = true;
//        }
//        catch (UnknownHostException e)
//        {
//            System.err.println("Unrecognized host: " + serverAddress);
//			System.exit(1);
//        }
//        catch (IOException e)
//        {
//            System.err.println("Could not connect to host: " + serverAddress);
//			System.exit(1);
//        }
        
//		System.out.println("mark 0");
		InputReader systemRead = new InputReader(cpacket);	//read user input from command line (testing only)
        ReadInput reader = this.new ReadInput();
	    SendOutput sender = this.new SendOutput();
	    
//	    System.out.println("mark 1");
	    
	    sender.start();
	    reader.start();
	    systemRead.start();
	}
	
	//private classes//
	
	
	private class ReadInput extends Thread
	{
		public void run()
		{
			ObjectInputStream objIn = null;
			try
			{
				//get object stream from socket
				objIn = new ObjectInputStream(socket.getInputStream());
				//
				
				while(connected) //read loop
	    		{
	    			//read in next packet
					ServerPacket sp = null;
					try
					{
						Object o = objIn.readObject(); //listen for next object from stream
						
						//interpret received server packet
						if(o instanceof ServerPacket)
						{
							sp = (ServerPacket)o;
							spacket = sp;
						}
						else
						{
							clientNumber = ((Integer)o).intValue();
							System.out.println("client num recieved: " + clientNumber);
						}
						//
						
						//print out server info for this client
						if(false)//(spacket != null)
						{
							System.out.println("YOU: (" + spacket.shipPositions[clientNumber][0] + ", " + spacket.shipPositions[clientNumber][1] + ") angle: " + spacket.shipPositions[clientNumber][2] + "0 deg.");
							
							//print other ships
							System.out.print("OTHER SHIPS: ");
							for(int j = 0; j < spacket.shipPositions.length; ++j)
							{
								if(spacket.shipPositions[j][0] >= 0 && j != clientNumber)
								{
									System.out.print("(" + spacket.shipPositions[j][0] + ", " + spacket.shipPositions[j][1] + " : " + spacket.shipPositions[j][2] + "0)  -  ");
								}
							}
							System.out.println();
							//
							
							//print out bullet locations
							System.out.print("BULLETS: ");
							for(int k = 0; k < spacket.bulletPositions.length; ++k)
							{
								if(spacket.bulletPositions[k][0] != 0)
								{
									System.out.print("(" + (short)spacket.bulletPositions[k][0] + ", " + (short)spacket.bulletPositions[k][1] + ") - ");
								}
							}
							System.out.println();
							//
							
						}
						//
						
						if(sp != null)
						{
							if(oldMessages == null)
							{
								oldMessages = new String[sp.messages.length];
							}
							for(int i = 0; i < sp.messages.length; ++i)
							{
								if(sp.messages[i] != null && !sp.messages[i].equals(oldMessages[i]))
								{
									oldMessages[i] = sp.messages[i];
									System.out.println(sp.messages[i]);
								}
							}
							
						}
			//			System.out.println("read from server");
					}
					catch(Exception e)
					{
						e.printStackTrace();
						connected = false;
					}
					//
					
					//wait specified number of milliseconds
//	    			try
//	    			{
//	    				sleep(200);
//	    			}
//	    			catch(Exception e)
//	    			{
//	    				e.printStackTrace();
//	    			}
	    			//
	    		}
	    		
	    		//cleanup
	    		objIn.close();
	    		socket.close();
	    		//
			}
			catch(IOException e)
	    	{
	    		e.printStackTrace();
	    	}
		}
	}
	
	private class SendOutput extends Thread
	{
		int threadWait = GameManager.GAME_SPEED;
		
		public void run()
		{
			ObjectOutputStream objOut = null;
			
//			System.err.println("send mark 1");
			try
			{
				//create object output stream for client socket
				objOut = new ObjectOutputStream(socket.getOutputStream());
				//
//				System.out.println("send initiated");
				while(connected)
				{
					int t = (int)System.currentTimeMillis(); //get current time
					
					objOut.reset();
					objOut.writeObject(cpacket);
//					cpacket.message = "";	//clear message after sending
					//
					
					//System.out.println("client send lag: " + ((int)System.currentTimeMillis() - t));
					if((int)System.currentTimeMillis() - t > threadWait) //check if packet sending took longer than threaWait
					{
						threadWait = 5; //minimum wait
					}
					else
					{
						threadWait = threadWait - ((int)System.currentTimeMillis() - t); //subtract time difference from threadWait (wait time until next packet send)
					}
					
					//wait specified number of milliseconds
	    			try
	    			{
	    				sleep(threadWait);
	    			}
	    			catch(Exception e)
	    			{
	    				e.printStackTrace();
	    			}
	    			//
	    			
	    			threadWait = GameManager.GAME_SPEED; //reset threadWait variable
				}
				
				//cleanup
				objOut.close();
				socket.close();
				//
			}
			catch(IOException e)
	    	{
	    		e.printStackTrace();
	    	}
		}
	}
}
